package ru.vsu.cs.pm.beans;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import ru.vsu.cs.pm.Utils.MD5HashUtils;
import ru.vsu.cs.pm.models.*;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;

/**
 * User: Oleg
 * Date: 19.12.2010
 */
@Component
public class UserManagerImpl implements UserManager{

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private ItemManager itemManager;

    @Autowired
    private AccountManager accountManager;

    @Transactional(readOnly = true)
    public List<User> findUserAll() {
        List users = entityManager.createNamedQuery("user.find.all").getResultList();
        return users;
    }

    @Transactional
    public User authenticate(String userName, String password) {
        List users = entityManager
                .createNamedQuery("user.authenticate")
                .setParameter("userName", userName)
                .getResultList();
        if (users.size() > 1) {
            throw new IllegalStateException("Non-unique user detected:" + userName);
        }
        if (users.size() < 1) {
            return null;
        }
        User user = (User) users.get(0);
        String passHash = MD5HashUtils.getMd5Digest(user.getUserName() + password);
        return passHash.equalsIgnoreCase(user.getPasswordHash()) ? user : null;
    }

    @Transactional
    public User registerUser(String userName, String password) {
        User user = new User();
        user.setUserName(userName);
        user.setPasswordHash(password);

        String passwordHash = MD5HashUtils.getMd5Digest(user.getUserName() + user.getPasswordHash());
        user.setPasswordHash(passwordHash);
        try{
            entityManager.persist(user);

            Item expenseItem = new Item();
            expenseItem.setUser(user);
            expenseItem.setRootItem(true);
            expenseItem.setParent(null);
            expenseItem.setTitle("All expenses");
            expenseItem.setDescription("Root item for the expenses");
            expenseItem.setChildrenCount(0);
            expenseItem.setType(ItemType.EXPENSE);
            itemManager.saveOrUpdateItem(expenseItem);

            Item incomeItem = new Item();
            incomeItem.setUser(user);
            incomeItem.setRootItem(true);
            incomeItem.setParent(null);
            incomeItem.setTitle("All incomes");
            incomeItem.setDescription("Root item for the incomes");
            incomeItem.setChildrenCount(0);
            incomeItem.setType(ItemType.INCOME);
            itemManager.saveOrUpdateItem(incomeItem);


            Item transferItem = new Item();
            transferItem.setUser(user);
            transferItem.setRootItem(true);
            transferItem.setParent(null);
            transferItem.setTitle("All transfers");
            transferItem.setDescription("Root item for the incomes");
            transferItem.setChildrenCount(0);
            transferItem.setType(ItemType.TRANSFER);
            itemManager.saveOrUpdateItem(transferItem);

            Item reserveItem = new Item();
            reserveItem.setUser(user);
            reserveItem.setRootItem(true);
            reserveItem.setParent(null);
            reserveItem.setTitle("All reserves");
            reserveItem.setDescription("Root item for the Reserves");
            reserveItem.setChildrenCount(0);
            reserveItem.setType(ItemType.RESERVE);
            itemManager.saveOrUpdateItem(reserveItem);

            Account reserveAccount = new Account();
            reserveAccount.setUser(user);
            reserveAccount.setTitle("Reserve account");
            reserveAccount.setMoney(new Long(0));
            reserveAccount.setDescription("Reserve account");
            reserveAccount.setType(AccountType.RESERVE);
            accountManager.saveOrUpdateAccount(reserveAccount);

            return user;
        } catch(Exception exc) {
            return null;
        }
    }
}
